package com.flying.flow.service;

import java.util.List;

import com.flying.common.annotation.DaoCreate;
import com.flying.common.annotation.DaoQuery;
import com.flying.common.annotation.DaoRemove;
import com.flying.common.annotation.DaoUpdate;
import com.flying.common.util.Codes;
import com.flying.common.util.Utils;
import com.flying.flow.model.Node;
import com.flying.flow.model.Node.AllowSplit;
import com.flying.flow.model.Node.EmergencyLevel;
import com.flying.flow.model.Node.FinishCondition;
import com.flying.flow.model.Node.NodeType;
import com.flying.flow.model.Node.PriorityLevel;
import com.flying.flow.model.Node.RouteMode;
import com.flying.flow.model.Node.TaskMode;
import com.flying.flow.model.Node.TaskStartType;
import com.flying.flow.model.NodeTransition;
import com.flying.framework.annotation.MethodInfo;
import com.flying.framework.annotation.Param;
import com.flying.framework.annotation.Service;
import com.flying.framework.model.ActionResult;
import com.flying.framework.model.ModelFactory;
import com.flying.framework.model.QueryResult;
import com.flying.framework.service.AbstractService;

@Service(value="NodeService", desc="流程节点")
public class NodeService extends AbstractService{
	private FlowDefinitionService fds;
	private NodeTransitionService nts;
	
	public void setFlowDefinitionService(FlowDefinitionService s) {
		this.fds = s;
	}
	
	public void setNodeTransitionService(NodeTransitionService s) {
		this.nts = s;
	}
	
	@MethodInfo("新增")
	@DaoCreate(entity=Node.ENTITY_NAME)
	public Node create(
			@Param(value=Node.FLOW_DEF_ID, required=true,	desc="流程定义ID") Long flow_def_id,
			@Param(value=Node.NAME, required=true,	desc="名称") String name,
			@Param(value=Node.REMARKS, required=false,	desc="说明") String remarks,
			
			@Param(value=Node.NODE_TYPE, required=true, enumClass=NodeType.class,	desc="节点类型") Integer node_type,
			@Param(value=Node.EMERGENCY_LEVEL, required=false, enumClass=EmergencyLevel.class,	desc="紧急程度") Integer emergency_level,
			@Param(value=Node.PRIORITY_LEVEL, required=false, enumClass=PriorityLevel.class,	desc="优先级别") Integer priority_level,
			@Param(value=Node.EXPECT_TIME, required=false,	desc="期望完成时间") String expect_time,
			@Param(value=Node.TASK_MODE, required=false, enumClass=TaskMode.class,	desc="任务执行模式") Integer task_mode,
			@Param(value=Node.ALLOW_SPLIT, required=false, enumClass=AllowSplit.class,	desc="允许拆分任务") Integer allow_split,
			@Param(value=Node.ROUTE_MODE, required=false, enumClass=RouteMode.class,	desc="任务执行模式") Integer route_mode,
			@Param(value=Node.TASK_START_TYPE, required=false, enumClass=TaskStartType.class,	desc="任务启动类型") Integer taskStartType,
			
			@Param(value=Node.FORM_ACTION, required=false,	desc="表单行为") String form_action,
			@Param(value=Node.FORM_CODE, required=false,	desc="表单代码") String form_code,
			@Param(value=Node.FORM_DATA, required=false,	desc="表单数据") String form_data,
			@Param(value=Node.PARTICIPANT_TYPE, required=false,	desc="执行人类型") String participant_type,
			@Param(value=Node.PARTICIPANTS_SOURCE, required=false,	desc="执行人来源") String participants_source,
			
			@Param(value=Node.EVENT_ON_LEAVE, required=false,	desc="结束事件") String event_on_leave,
			@Param(value=Node.EVENT_ON_ENTER, required=false,	desc="开始事件") String event_on_enter,
			@Param(value=Node.FINISH_CONDITION, required=false, enumClass=FinishCondition.class,	desc="完成条件（1：一个Task完成；2：多数Task完成；3：所有Task完成）") Integer finish_condition
		) throws Exception {
		if(node_type == null) node_type = NodeType.NORMAL.value();
		if(emergency_level == null) emergency_level = EmergencyLevel.NORMAL.value();
		if(priority_level == null) priority_level = PriorityLevel.LOW.value();
		if(task_mode == null) task_mode = TaskMode.ONE_TASK_ONE_PARTICIPANT.value();
		if(allow_split == null) allow_split = AllowSplit.NOT_ALLOW.value();
		if(route_mode == null) route_mode = RouteMode.AUTO.value();
		if(taskStartType == null) taskStartType = TaskStartType.AUTO.value();
		this.fds.checkUpdatable(flow_def_id);
		return ModelFactory.create(Node.class, 
				Node.NODE_TYPE, node_type, 
				Node.EMERGENCY_LEVEL, emergency_level, 
				Node.PRIORITY_LEVEL, priority_level, 
				Node.TASK_MODE, task_mode,
				Node.ALLOW_SPLIT, allow_split, 
				Node.ROUTE_MODE, route_mode, 
				Node.TASK_START_TYPE, taskStartType);
	}
	
	@MethodInfo("新增")
	@DaoCreate(entity=Node.ENTITY_NAME)
	public Node create2(
			@Param(value=Node.FLOW_DEF_ID, required=true,	desc="流程定义ID") Long flow_def_id,
			@Param(value=Node.NAME, required=true,	desc="名称") String name,
			@Param(value=Node.REMARKS, required=false,	desc="说明") String remarks,
			@Param(value=Node.TASK_MODE, required=false, enumClass=TaskMode.class,	desc="任务执行模式") Integer task_mode,
			@Param(value=Node.ALLOW_SPLIT, required=false, enumClass=AllowSplit.class,	desc="允许拆分任务") Integer allow_split,
			@Param(value=Node.ROUTE_MODE, required=false, enumClass=RouteMode.class,	desc="任务执行模式") Integer route_mode,
			@Param(value=Node.TASK_START_TYPE, required=false, enumClass=TaskStartType.class,	desc="任务启动类型") Integer taskStartType,
			@Param(value=Node.NODE_TYPE, required=true, enumClass=NodeType.class,	desc="节点类型：0：开始节点；1：普通节点；2：自动节点；9：终止节点") Integer node_type,
			@Param(value=Node.FINISH_CONDITION, required=false, enumClass=FinishCondition.class,	desc="完成条件（1：一个Task完成；2：多数Task完成；3：所有Task完成）") Integer finish_condition
		) throws Exception {
		this.fds.checkUpdatable(flow_def_id);
		return null;
	}
	
	@MethodInfo("克隆")
	@DaoCreate(entity=Node.ENTITY_NAME)
	public Node cloneNode(
			@Param(value=Node.FLOW_DEF_ID, required=true,	desc="目标流程定义ID") Long flow_def_id,
			@Param(value=Node.NODE_ID, required=true,	desc="源节点ID") Long node_id
		) throws Exception {
		Node n = this.findById(node_id);
		return this.create(flow_def_id, n.getName(), n.getRemarks(), n.getNodeType(), n.getEmergencyLevel(), n.getPriorityLevel(),
				n.getExpectTime(), n.getTaskMode(), n.getAllowSplit(), n.getRouteMode(), n.getTaskStartType(), 
				n.getFormAction(), n.getFormCode(), n.getFormData(), n.getParticipantType(), n.getParticipantsSource(),
				n.getEventOnLeave(), n.getEventOnEnter(), n.getFinishCondition());
	}

	@MethodInfo("修改")
	@DaoUpdate(entity=Node.ENTITY_NAME)
	public ActionResult update(
			@Param(value=Node.NODE_ID, required=true,	desc="节点ID") Long node_id,
			@Param(value=Node.NAME, required=true,	desc="名称") String name,
			@Param(value=Node.REMARKS, required=false,	desc="说明") String remarks,
			@Param(value=Node.NODE_TYPE, required=true, enumClass=NodeType.class,	desc="节点类型：0：开始节点；1：普通节点；2：自动节点；9：终止节点") Integer node_type,
			@Param(value=Node.EMERGENCY_LEVEL, required=false,	desc="紧急程度") Integer emergency_level,
			@Param(value=Node.PRIORITY_LEVEL, required=false,	desc="优先级别") Integer priority_level,
			@Param(value=Node.EXPECT_TIME, required=false,	desc="期望完成时间") String expect_time,
			@Param(value=Node.TASK_MODE, required=false, enumClass=TaskMode.class,	desc="任务执行模式（0：指定；1：抢占；2：传承）") Integer task_mode,
			@Param(value=Node.ALLOW_SPLIT, required=false, enumClass=AllowSplit.class,	desc="允许拆分任务") Integer allow_split,
			@Param(value=Node.FORM_ACTION, required=false,	desc="表单行为") String form_action,
			@Param(value=Node.FORM_CODE, required=false,	desc="表单代码") String form_code,
			@Param(value=Node.PARTICIPANT_TYPE, required=false,	desc="执行人类型") String participant_type,
			@Param(value=Node.PARTICIPANTS_SOURCE, required=false,	desc="执行人来源") String participants_source,
			@Param(value=Node.EVENT_ON_LEAVE, required=false,	desc="结束事件") String event_on_finish,
			@Param(value=Node.EVENT_ON_ENTER, required=false,	desc="开始事件") String event_on_start,
			@Param(value=Node.FINISH_CONDITION, required=false, enumClass=FinishCondition.class,	desc="完成条件（1：一个Task完成；2：多数Task完成；3：所有Task完成）") Integer finish_condition
			
		) throws Exception {
		Node n = this.findById(node_id);
		this.fds.checkUpdatable(n.getFlowDefId());
		return null;
	}

	@MethodInfo("删除")
	@DaoRemove(entity=Node.ENTITY_NAME)
	public ActionResult remove(
			@Param(value=Node.NODE_ID, required=true,	desc="节点ID") Long node_id
		) throws Exception {
		
		return null;
	}

	@MethodInfo("删除")
	@DaoRemove(entity=Node.ENTITY_NAME)
	public ActionResult removeByFlowDefinitionId(
			@Param(value=Node.FLOW_DEF_ID, required=true,	desc="流程定义ID") Long flow_def_id
		) throws Exception {
		
		return null;
	}

	@MethodInfo("搜索")
	@DaoQuery(entity=Node.ENTITY_NAME, pageable=true, modelClass=Node.class)
	public QueryResult<Node> findAll(
			@Param(value=Codes.PAGE_NUM, 	required=false, desc="分页页号，默认0") int page,
			@Param(value=Codes.PAGE_SIZE, 	required=false, desc="分页大小，默认10") int rows) throws Exception {
		return null;
	}

	@MethodInfo("搜索")
	@DaoQuery(entity=Node.ENTITY_NAME, pageable=false, modelClass=Node.class)
	public QueryResult<Node> findByFlowDefinitionId(
			@Param(value=Node.FLOW_DEF_ID, required=true,	desc="流程定义ID") Long flow_def_id) throws Exception {
		return null;
	}

	@SuppressWarnings("unchecked")
	@MethodInfo("搜索")
	public QueryResult<Node> findNextNodes(
			@Param(value=Node.NODE_ID, required=true,	desc="节点ID") Long node_id) throws Exception {
		List<NodeTransition> lnt = this.nts.findByFromNodeId(node_id).getRows();
		final List<Node> list = Utils.newArrayList();
		lnt.stream().forEach(x -> {
			list.add(findById(x.getToNodeId()));
		});
		return ModelFactory.create(QueryResult.class, Codes.ROWS, list);
	}

	@MethodInfo("查询")
	@DaoQuery(entity=Node.ENTITY_NAME, single=true, throwsNotFoundException=true )
	public Node findById(
			@Param(value=Node.NODE_ID, required=true,	desc="节点ID") Long node_id
		) {
		return null;
	}

}